package darklaunch

import (
	"crypto/sha256"
	"fmt"
)

type DarkConfig struct {
	Configs map[string]*DarkRule `yaml:"configs" json:"configs"`
}

//```
//configs:
//feature1:
//key: "feature1"
//enabled: true
//typ: "simple"
//values: ["value1", "value2"]
//rangeSet: [[10,20], [30,40]]
//percentage: 50
//feature2:
//key: "feature2"
//enabled: false
//typ: "complex"
//values: ["valueA", "valueB"]
//rangeSet: [[100,200], [300,400]]
//percentage: 75
//```

type DarkFeature interface {
	Enabled() bool
	Dark(darkTarget interface{}) bool
}

type DarkRule struct {
	Key        string        `yaml:"key" json:"key"`
	Enable     bool          `yaml:"enabled" json:"enabled"`
	Typ        string        `yaml:"typ" json:"typ"`
	Values     []interface{} `yaml:"values" json:"values"`
	RangeSet   [][2]int      `yaml:"rangeSet" json:"rangeSet"`
	Percentage int           `yaml:"percentage" json:"percentage"`
}

func (d *DarkRule) Enabled() bool {
	return d.Enable
}

func (d *DarkRule) Dark(darkTarget interface{}) bool {
	if !d.Enable {
		return false
	}

	for _, val := range d.Values {
		if val == darkTarget {
			return true
		}
	}

	if darkTargetInt, ok := darkTarget.(int); ok {
		for _, item := range d.RangeSet {
			if item[0] <= darkTargetInt && darkTargetInt <= item[1] {
				return true
			}
		}
	}

	strTarget := fmt.Sprintf("%v", darkTarget)
	h := sha256.New()
	h.Write([]byte(strTarget))
	hashVal := h.Sum(nil)

	// Map the first byte of the hash to a value between 0 and 100.
	mappedVal := int(hashVal[0]) % 101
	if mappedVal <= d.Percentage {
		return true
	}
	return false
}
